home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / mosmlyac / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  32.1 KB  |  1,802 lines  |  [TEXT/R*ch]

  1. #include "defs.h"
  2.  
  3. /*  The line size must be a positive integer.  One hundred was chosen    */
  4. /*  because few lines in Yacc input grammars exceed 100 characters.    */
  5. /*  Note that if a line exceeds LINESIZE characters, the line buffer    */
  6. /*  will be expanded to accomodate it.                    */
  7.  
  8. #define LINESIZE 100
  9.  
  10. char *cache;
  11. int cinc, cache_size;
  12.  
  13. int ntags, tagmax;
  14. char **tag_table;
  15.  
  16. char saw_eof, unionized;
  17. char *cptr, *line;
  18. int linesize;
  19.  
  20. bucket *goal;
  21. int prec;
  22. int gensym;
  23. char last_was_action;
  24.  
  25. int maxitems;
  26. bucket **pitem;
  27.  
  28. int maxrules;
  29. bucket **plhs;
  30.  
  31. int name_pool_size;
  32. char *name_pool;
  33.  
  34. char line_format[] = "(* Line %d, file %s *)\n";
  35.  
  36.  
  37. cachec(c)
  38. int c;
  39. {
  40.     assert(cinc >= 0);
  41.     if (cinc >= cache_size)
  42.     {
  43.     cache_size += 256;
  44.     cache = REALLOC(cache, cache_size);
  45.     if (cache == 0) no_space();
  46.     }
  47.     cache[cinc] = c;
  48.     ++cinc;
  49. }
  50.  
  51.  
  52. get_line()
  53. {
  54.     register FILE *f = input_file;
  55.     register int c;
  56.     register int i;
  57.  
  58.     if (saw_eof || (c = getc(f)) == EOF)
  59.     {
  60.     if (line) { FREE(line); line = 0; }
  61.     cptr = 0;
  62.     saw_eof = 1;
  63.     return;
  64.     }
  65.  
  66.     if (line == 0 || linesize != (LINESIZE + 1))
  67.     {
  68.     if (line) FREE(line);
  69.     linesize = LINESIZE + 1;
  70.     line = MALLOC(linesize);
  71.     if (line == 0) no_space();
  72.     }
  73.  
  74.     i = 0;
  75.     ++lineno;
  76.     for (;;)
  77.     {
  78.     line[i]  =  c;
  79.     if (c == '\n') { cptr = line; return; }
  80.     if (++i >= linesize)
  81.     {
  82.         linesize += LINESIZE;
  83.         line = REALLOC(line, linesize);
  84.         if (line ==  0) no_space();
  85.     }
  86.     c = getc(f);
  87.     if (c ==  EOF)
  88.     {
  89.         line[i] = '\n';
  90.         saw_eof = 1;
  91.         cptr = line;
  92.         return;
  93.     }
  94.     }
  95. }
  96.  
  97.  
  98. char *
  99. dup_line()
  100. {
  101.     register char *p, *s, *t;
  102.  
  103.     if (line == 0) return (0);
  104.     s = line;
  105.     while (*s != '\n') ++s;
  106.     p = MALLOC(s - line + 1);
  107.     if (p == 0) no_space();
  108.  
  109.     s = line;
  110.     t = p;
  111.     while ((*t++ = *s++) != '\n') continue;
  112.     return (p);
  113. }
  114.  
  115.  
  116. skip_comment()
  117. {
  118.     register char *s;
  119.  
  120.     int st_lineno = lineno;
  121.     char *st_line = dup_line();
  122.     char *st_cptr = st_line + (cptr - line);
  123.  
  124.     s = cptr + 2;
  125.     for (;;)
  126.     {
  127.     if (*s == '*' && s[1] == '/')
  128.     {
  129.         cptr = s + 2;
  130.         FREE(st_line);
  131.         return;
  132.     }
  133.     if (*s == '\n')
  134.     {
  135.         get_line();
  136.         if (line == 0)
  137.         unterminated_comment(st_lineno, st_line, st_cptr);
  138.         s = cptr;
  139.     }
  140.     else
  141.         ++s;
  142.     }
  143. }
  144.  
  145.  
  146. int
  147. nextc()
  148. {
  149.     register char *s;
  150.  
  151.     if (line == 0)
  152.     {
  153.     get_line();
  154.     if (line == 0)
  155.         return (EOF);
  156.     }
  157.  
  158.     s = cptr;
  159.     for (;;)
  160.     {
  161.     switch (*s)
  162.     {
  163.     case '\n':
  164.         get_line();
  165.         if (line == 0) return (EOF);
  166.         s = cptr;
  167.         break;
  168.  
  169.     case ' ':
  170.     case '\t':
  171.     case '\f':
  172.     case '\r':
  173.     case '\v':
  174.     case ',':
  175.     case ';':
  176.         ++s;
  177.         break;
  178.  
  179.     case '\\':
  180.         cptr = s;
  181.         return ('%');
  182.  
  183.     case '/':
  184.         if (s[1] == '*')
  185.         {
  186.         cptr = s;
  187.         skip_comment();
  188.         s = cptr;
  189.         break;
  190.         }
  191.         else if (s[1] == '/')
  192.         {
  193.         get_line();
  194.         if (line == 0) return (EOF);
  195.         s = cptr;
  196.         break;
  197.         }
  198.         /* fall through */
  199.  
  200.     default:
  201.         cptr = s;
  202.         return (*s);
  203.     }
  204.     }
  205. }
  206.  
  207.  
  208. int
  209. keyword()
  210. {
  211.     register int c;
  212.     char *t_cptr = cptr;
  213.  
  214.     c = *++cptr;
  215.     if (isalpha(c))
  216.     {
  217.     cinc = 0;
  218.     for (;;)
  219.     {
  220.         if (isalpha(c))
  221.         {
  222.         if (isupper(c)) c = tolower(c);
  223.         cachec(c);
  224.         }
  225.         else if (isdigit(c) || c == '_' || c == '.' || c == '$')
  226.         cachec(c);
  227.         else
  228.         break;
  229.         c = *++cptr;
  230.     }
  231.     cachec(NUL);
  232.  
  233.     if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  234.         return (TOKEN);
  235.     if (strcmp(cache, "type") == 0)
  236.         return (TYPE);
  237.     if (strcmp(cache, "left") == 0)
  238.         return (LEFT);
  239.     if (strcmp(cache, "right") == 0)
  240.         return (RIGHT);
  241.     if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  242.         return (NONASSOC);
  243.     if (strcmp(cache, "start") == 0)
  244.         return (START);
  245.     if (strcmp(cache, "union") == 0)
  246.         return (UNION);
  247.     if (strcmp(cache, "ident") == 0)
  248.         return (IDENT);
  249.     }
  250.     else
  251.     {
  252.     ++cptr;
  253.     if (c == '{')
  254.         return (TEXT);
  255.     if (c == '%' || c == '\\')
  256.         return (MARK);
  257.     if (c == '<')
  258.         return (LEFT);
  259.     if (c == '>')
  260.         return (RIGHT);
  261.     if (c == '0')
  262.         return (TOKEN);
  263.     if (c == '2')
  264.         return (NONASSOC);
  265.     }
  266.     syntax_error(lineno, line, t_cptr);
  267.     /*NOTREACHED*/
  268. }
  269.  
  270.  
  271. copy_ident()
  272. {
  273.     register int c;
  274.     register FILE *f = output_file;
  275.  
  276.     c = nextc();
  277.     if (c == EOF) unexpected_EOF();
  278.     if (c != '"') syntax_error(lineno, line, cptr);
  279.     ++outline;
  280.     fprintf(f, "#ident \"");
  281.     for (;;)
  282.     {
  283.     c = *++cptr;
  284.     if (c == '\n')
  285.     {
  286.         fprintf(f, "\"\n");
  287.         return;
  288.     }
  289.     putc(c, f);
  290.     if (c == '"')
  291.     {
  292.         putc('\n', f);
  293.         ++cptr;
  294.         return;
  295.     }
  296.     }
  297. }
  298.  
  299.  
  300. copy_text()
  301. {
  302.     register int c;
  303.     int quote;
  304.     register FILE *f = text_file;
  305.     int need_newline = 0;
  306.     int t_lineno = lineno;
  307.     char *t_line = dup_line();
  308.     char *t_cptr = t_line + (cptr - line - 2);
  309.  
  310.     if (*cptr == '\n')
  311.     {
  312.     get_line();
  313.     if (line == 0)
  314.         unterminated_text(t_lineno, t_line, t_cptr);
  315.     }
  316.  
  317. loop:
  318.     c = *cptr++;
  319.     switch (c)
  320.     {
  321.     case '\n':
  322.     next_line:
  323.     putc('\n', f);
  324.     need_newline = 0;
  325.     get_line();
  326.     if (line) goto loop;
  327.     unterminated_text(t_lineno, t_line, t_cptr);
  328.  
  329.     case '`':
  330.     case '"':
  331.     {
  332.         int s_lineno = lineno;
  333.         char *s_line = dup_line();
  334.         char *s_cptr = s_line + (cptr - line - 1);
  335.  
  336.         quote = c;
  337.         putc(c, f);
  338.         for (;;)
  339.         {
  340.         c = *cptr++;
  341.         putc(c, f);
  342.         if (c == quote)
  343.         {
  344.             need_newline = 1;
  345.             FREE(s_line);
  346.             goto loop;
  347.         }
  348.         if (c == '\n')
  349.             unterminated_string(s_lineno, s_line, s_cptr);
  350.         if (c == '\\')
  351.         {
  352.             c = *cptr++;
  353.             putc(c, f);
  354.             if (c == '\n')
  355.             {
  356.             get_line();
  357.             if (line == 0)
  358.                 unterminated_string(s_lineno, s_line, s_cptr);
  359.             }
  360.         }
  361.         }
  362.     }
  363.  
  364.     case '(':
  365.     putc(c, f);
  366.     need_newline = 1;
  367.     c = *cptr;
  368.     if (c == '*')
  369.     {
  370.         int c_lineno = lineno;
  371.         char *c_line = dup_line();
  372.         char *c_cptr = c_line + (cptr - line - 1);
  373.  
  374.         putc('*', f);
  375.         ++cptr;
  376.         for (;;)
  377.         {
  378.         c = *cptr++;
  379.         putc(c, f);
  380.         if (c == '*' && *cptr == ')')
  381.         {
  382.             putc(')', f);
  383.             ++cptr;
  384.             FREE(c_line);
  385.             goto loop;
  386.         }
  387.         if (c == '\n')
  388.         {
  389.             get_line();
  390.             if (line == 0)
  391.             unterminated_comment(c_lineno, c_line, c_cptr);
  392.         }
  393.         }
  394.     }
  395.     need_newline = 1;
  396.     goto loop;
  397.  
  398.     case '%':
  399.     case '\\':
  400.     if (*cptr == '}')
  401.     {
  402.         if (need_newline) putc('\n', f);
  403.         ++cptr;
  404.         FREE(t_line);
  405.         return;
  406.     }
  407.     /* fall through */
  408.  
  409.     default:
  410.     putc(c, f);
  411.     need_newline = 1;
  412.     goto loop;
  413.     }
  414. }
  415.  
  416.  
  417. copy_union()
  418. {
  419.     register int c;
  420.     int quote;
  421.     int depth;
  422.     int u_lineno = lineno;
  423.     char *u_line = dup_line();
  424.     char *u_cptr = u_line + (cptr - line - 6);
  425.  
  426.     if (unionized) over_unionized(cptr - 6);
  427.     unionized = 1;
  428.  
  429.     if (!lflag)
  430.     fprintf(text_file, line_format, lineno, input_file_name);
  431.  
  432.     fprintf(text_file, "typedef union");
  433.     if (dflag) fprintf(union_file, "typedef union");
  434.  
  435.     depth = 1;
  436.     cptr++;
  437.  
  438. loop:
  439.     c = *cptr++;
  440.     putc(c, text_file);
  441.     if (dflag) putc(c, union_file);
  442.     switch (c)
  443.     {
  444.     case '\n':
  445.     next_line:
  446.     get_line();
  447.     if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  448.     goto loop;
  449.  
  450.     case '{':
  451.     ++depth;
  452.     goto loop;
  453.  
  454.     case '}':
  455.         --depth;
  456.         if (c == '}' && depth == 0) {
  457.           fprintf(text_file, " YYSTYPE;\n");
  458.           FREE(u_line);
  459.           return;
  460.         }
  461.         goto loop;
  462.  
  463.     case '\'':
  464.     case '"':
  465.     {
  466.         int s_lineno = lineno;
  467.         char *s_line = dup_line();
  468.         char *s_cptr = s_line + (cptr - line - 1);
  469.  
  470.         quote = c;
  471.         for (;;)
  472.         {
  473.         c = *cptr++;
  474.         putc(c, text_file);
  475.         if (dflag) putc(c, union_file);
  476.         if (c == quote)
  477.         {
  478.             FREE(s_line);
  479.             goto loop;
  480.         }
  481.         if (c == '\n')
  482.             unterminated_string(s_lineno, s_line, s_cptr);
  483.         if (c == '\\')
  484.         {
  485.             c = *cptr++;
  486.             putc(c, text_file);
  487.             if (dflag) putc(c, union_file);
  488.             if (c == '\n')
  489.             {
  490.             get_line();
  491.             if (line == 0)
  492.                 unterminated_string(s_lineno, s_line, s_cptr);
  493.             }
  494.         }
  495.         }
  496.     }
  497.  
  498.     case '(':
  499.     c = *cptr;
  500.     if (c == '*')
  501.     {
  502.         int c_lineno = lineno;
  503.         char *c_line = dup_line();
  504.         char *c_cptr = c_line + (cptr - line - 1);
  505.  
  506.         putc('*', text_file);
  507.         if (dflag) putc('*', union_file);
  508.         ++cptr;
  509.         for (;;)
  510.         {
  511.         c = *cptr++;
  512.         putc(c, text_file);
  513.         if (dflag) putc(c, union_file);
  514.         if (c == '*' && *cptr == ')')
  515.         {
  516.             putc(')', text_file);
  517.             if (dflag) putc(')', union_file);
  518.             ++cptr;
  519.             FREE(c_line);
  520.             goto loop;
  521.         }
  522.         if (c == '\n')
  523.         {
  524.             get_line();
  525.             if (line == 0)
  526.             unterminated_comment(c_lineno, c_line, c_cptr);
  527.         }
  528.         }
  529.     }
  530.     goto loop;
  531.  
  532.     default:
  533.     goto loop;
  534.     }
  535. }
  536.  
  537.  
  538. int
  539. hexval(c)
  540. int c;
  541. {
  542.     if (c >= '0' && c <= '9')
  543.     return (c - '0');
  544.     if (c >= 'A' && c <= 'F')
  545.     return (c - 'A' + 10);
  546.     if (c >= 'a' && c <= 'f')
  547.     return (c - 'a' + 10);
  548.     return (-1);
  549. }
  550.  
  551.  
  552. bucket *
  553. get_literal()
  554. {
  555.     register int c, quote;
  556.     register int i;
  557.     register int n;
  558.     register char *s;
  559.     register bucket *bp;
  560.     int s_lineno = lineno;
  561.     char *s_line = dup_line();
  562.     char *s_cptr = s_line + (cptr - line);
  563.  
  564.     quote = *cptr++;
  565.     cinc = 0;
  566.     for (;;)
  567.     {
  568.     c = *cptr++;
  569.     if (c == quote) break;
  570.     if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  571.     if (c == '\\')
  572.     {
  573.         char *c_cptr = cptr - 1;
  574.  
  575.         c = *cptr++;
  576.         switch (c)
  577.         {
  578.         case '\n':
  579.         get_line();
  580.         if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  581.         continue;
  582.  
  583.         case '0': case '1': case '2': case '3':
  584.         case '4': case '5': case '6': case '7':
  585.         n = c - '0';
  586.         c = *cptr;
  587.         if (IS_OCTAL(c))
  588.         {
  589.             n = (n << 3) + (c - '0');
  590.             c = *++cptr;
  591.             if (IS_OCTAL(c))
  592.             {
  593.             n = (n << 3) + (c - '0');
  594.             ++cptr;
  595.             }
  596.         }
  597.         if (n > MAXCHAR) illegal_character(c_cptr);
  598.         c = n;
  599.             break;
  600.  
  601.         case 'x':
  602.         c = *cptr++;
  603.         n = hexval(c);
  604.         if (n < 0 || n >= 16)
  605.             illegal_character(c_cptr);
  606.         for (;;)
  607.         {
  608.             c = *cptr;
  609.             i = hexval(c);
  610.             if (i < 0 || i >= 16) break;
  611.             ++cptr;
  612.             n = (n << 4) + i;
  613.             if (n > MAXCHAR) illegal_character(c_cptr);
  614.         }
  615.         c = n;
  616.         break;
  617.  
  618.         case 'a': c = 7; break;
  619.         case 'b': c = '\b'; break;
  620.         case 'f': c = '\f'; break;
  621.         case 'n': c = '\n'; break;
  622.         case 'r': c = '\r'; break;
  623.         case 't': c = '\t'; break;
  624.         case 'v': c = '\v'; break;
  625.         }
  626.     }
  627.     cachec(c);
  628.     }
  629.     FREE(s_line);
  630.  
  631.     n = cinc;
  632.     s = MALLOC(n);
  633.     if (s == 0) no_space();
  634.  
  635.     for (i = 0; i < n; ++i)
  636.     s[i] = cache[i];
  637.  
  638.     cinc = 0;
  639.     if (n == 1)
  640.     cachec('\'');
  641.     else
  642.     cachec('"');
  643.  
  644.     for (i = 0; i < n; ++i)
  645.     {
  646.     c = ((unsigned char *)s)[i];
  647.     if (c == '\\' || c == cache[0])
  648.     {
  649.         cachec('\\');
  650.         cachec(c);
  651.     }
  652.     else if (isprint(c))
  653.         cachec(c);
  654.     else
  655.     {
  656.         cachec('\\');
  657.         switch (c)
  658.         {
  659.         case 7: cachec('a'); break;
  660.         case '\b': cachec('b'); break;
  661.         case '\f': cachec('f'); break;
  662.         case '\n': cachec('n'); break;
  663.         case '\r': cachec('r'); break;
  664.         case '\t': cachec('t'); break;
  665.         case '\v': cachec('v'); break;
  666.         default:
  667.         cachec(((c >> 6) & 7) + '0');
  668.         cachec(((c >> 3) & 7) + '0');
  669.         cachec((c & 7) + '0');
  670.         break;
  671.         }
  672.     }
  673.     }
  674.  
  675.     if (n == 1)
  676.     cachec('\'');
  677.     else
  678.     cachec('"');
  679.  
  680.     cachec(NUL);
  681.     bp = lookup(cache);
  682.     bp->class = TERM;
  683.     if (n == 1 && bp->value == UNDEFINED)
  684.     bp->value = *(unsigned char *)s;
  685.     FREE(s);
  686.  
  687.     return (bp);
  688. }
  689.  
  690.  
  691. int
  692. is_reserved(name)
  693. char *name;
  694. {
  695.     char *s;
  696.  
  697.     if (strcmp(name, ".") == 0 ||
  698.         strcmp(name, "$accept") == 0 ||
  699.         strcmp(name, "$end") == 0)
  700.     return (1);
  701.  
  702.     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  703.     {
  704.     s = name + 3;
  705.     while (isdigit(*s)) ++s;
  706.     if (*s == NUL) return (1);
  707.     }
  708.  
  709.     return (0);
  710. }
  711.  
  712.  
  713. bucket *
  714. get_name()
  715. {
  716.     register int c;
  717.  
  718.     cinc = 0;
  719.     for (c = *cptr; IS_IDENT(c); c = *++cptr)
  720.     cachec(c);
  721.     cachec(NUL);
  722.  
  723.     if (is_reserved(cache)) used_reserved(cache);
  724.  
  725.     return (lookup(cache));
  726. }
  727.  
  728.  
  729. int
  730. get_number()
  731. {
  732.     register int c;
  733.     register int n;
  734.  
  735.     n = 0;
  736.     for (c = *cptr; isdigit(c); c = *++cptr)
  737.     n = 10*n + (c - '0');
  738.  
  739.     return (n);
  740. }
  741.  
  742.  
  743. char *
  744. get_tag()
  745. {
  746.     register int c;
  747.     register int i;
  748.     register char *s;
  749.     int t_lineno = lineno;
  750.     char *t_line = dup_line();
  751.     char *t_cptr = t_line + (cptr - line);
  752.  
  753.     cinc = 0; 
  754.     {int last = ' ';  /* The character preceding the current one (c) */
  755.      while (1) {
  756.         c = *++cptr;
  757.         if (c == '\n') 
  758.       {last = c; c = nextc(); }
  759.         if (c == EOF) unexpected_EOF();
  760.         /* Do not take `->' to signify the end of a type specification: */
  761.         if ((c == '>') && (last != '-')) break;
  762.         cachec(c); last = c;
  763.      } }
  764.     ++cptr;
  765.     cachec(NUL);
  766.  
  767.     for (i = 0; i < ntags; ++i)
  768.     {
  769.     if (strcmp(cache, tag_table[i]) == 0)
  770.         return (tag_table[i]);
  771.     }
  772.  
  773.     if (ntags >= tagmax)
  774.     {
  775.     tagmax += 16;
  776.     tag_table = (char **)
  777.             (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  778.                    : MALLOC(tagmax*sizeof(char *)));
  779.     if (tag_table == 0) no_space();
  780.     }
  781.  
  782.     s = MALLOC(cinc);
  783.     if  (s == 0) no_space();
  784.     strcpy(s, cache);
  785.     tag_table[ntags] = s;
  786.     ++ntags;
  787.     FREE(t_line);
  788.     return (s);
  789. }
  790.  
  791.  
  792. declare_tokens(assoc)
  793. int assoc;
  794. {
  795.     register int c;
  796.     register bucket *bp;
  797.     int value;
  798.     char *tag = 0;
  799.  
  800.     if (assoc != TOKEN) ++prec;
  801.  
  802.     c = nextc();
  803.     if (c == EOF) unexpected_EOF();
  804.     if (c == '<')
  805.     {
  806.     tag = get_tag();
  807.     c = nextc();
  808.     if (c == EOF) unexpected_EOF();
  809.     }
  810.  
  811.     for (;;)
  812.     {
  813.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  814.         bp = get_name();
  815.     else if (c == '\'' || c == '"')
  816.         bp = get_literal();
  817.     else
  818.         return;
  819.  
  820.     if (bp == goal) tokenized_start(bp->name);
  821.     bp->class = TERM;
  822.  
  823.     if (tag)
  824.     {
  825.         if (bp->tag && tag != bp->tag)
  826.         retyped_warning(bp->name);
  827.         bp->tag = tag;
  828.     }
  829.  
  830.     if (assoc == TOKEN)
  831.         {
  832.             bp->true_token = 1;
  833.         }
  834.         else
  835.     {
  836.         if (bp->prec && prec != bp->prec)
  837.         reprec_warning(bp->name);
  838.         bp->assoc = assoc;
  839.         bp->prec = prec;
  840.     }
  841.  
  842.  
  843.     c = nextc();
  844.     if (c == EOF) unexpected_EOF();
  845.     value = UNDEFINED;
  846.     if (isdigit(c))
  847.     {
  848.         value = get_number();
  849.         if (bp->value != UNDEFINED && value != bp->value)
  850.         revalued_warning(bp->name);
  851.         bp->value = value;
  852.         c = nextc();
  853.         if (c == EOF) unexpected_EOF();
  854.     }
  855.     }
  856. }
  857.  
  858.  
  859. declare_types()
  860. {
  861.     register int c;
  862.     register bucket *bp;
  863.     char *tag;
  864.  
  865.     c = nextc();
  866.     if (c == EOF) unexpected_EOF();
  867.     if (c != '<') syntax_error(lineno, line, cptr);
  868.     tag = get_tag();
  869.  
  870.     for (;;)
  871.     {
  872.     c = nextc();
  873.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  874.         bp = get_name();
  875.     else if (c == '\'' || c == '"')
  876.         bp = get_literal();
  877.     else
  878.         return;
  879.  
  880.     if (bp->tag && tag != bp->tag)
  881.         retyped_warning(bp->name);
  882.     bp->tag = tag;
  883.     }
  884. }
  885.  
  886.  
  887. declare_start()
  888. {
  889.     register int c;
  890.     register bucket *bp;
  891.     static int entry_counter = 0;
  892.  
  893.     c = nextc();
  894.     if (c == EOF) unexpected_EOF();
  895.     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  896.     syntax_error(lineno, line, cptr);
  897.     bp = get_name();
  898.  
  899.     if (bp->class == TERM)
  900.     terminal_start(bp->name);
  901.     bp->entry = ++entry_counter;
  902.     if (entry_counter == 256)
  903.       too_many_entries();
  904. }
  905.  
  906.  
  907. read_declarations()
  908. {
  909.     register int c, k;
  910.  
  911.     cache_size = 256;
  912.     cache = MALLOC(cache_size);
  913.     if (cache == 0) no_space();
  914.  
  915.     for (;;)
  916.     {
  917.     c = nextc();
  918.     if (c == EOF) unexpected_EOF();
  919.     if (c != '%') syntax_error(lineno, line, cptr);
  920.     switch (k = keyword())
  921.     {
  922.     case MARK:
  923.         return;
  924.  
  925.     case IDENT:
  926.         copy_ident();
  927.         break;
  928.  
  929.     case TEXT:
  930.         copy_text();
  931.         break;
  932.  
  933.     case UNION:
  934.         copy_union();
  935.         break;
  936.  
  937.     case TOKEN:
  938.     case LEFT:
  939.     case RIGHT:
  940.     case NONASSOC:
  941.         declare_tokens(k);
  942.         break;
  943.  
  944.     case TYPE:
  945.         declare_types();
  946.         break;
  947.  
  948.     case START:
  949.         declare_start();
  950.         break;
  951.     }
  952.     }
  953. }
  954.  
  955. output_token_type(FILE *output_file)
  956. {
  957.   bucket * bp;
  958.   int n, tyno;
  959.  
  960.   fprintf(output_file, "local\n");
  961.  
  962.   /* Make type abbreviations for types that may be products or records: */
  963.   tyno = 1;
  964.   for (bp = first_symbol; bp; bp = bp->next) {
  965.     if (bp->class == TERM && bp->true_token && bp->tag 
  966.         && (strchr(bp->tag, '*') || strchr(bp->tag, '{')))
  967.     {
  968.       fprintf(output_file, "type t__%d__ = %s\n", tyno, bp->tag);
  969.       tyno++;
  970.     }
  971.   }
  972.   fprintf(output_file, "in\n");
  973.  
  974.   /* Output the token datatype, using the type abbreviations: */  
  975.   fprintf(output_file, "datatype token =\n");
  976.   n = 0; tyno = 1;
  977.   for (bp = first_symbol; bp; bp = bp->next) {
  978.     if (bp->class == TERM && bp->true_token) {
  979.       fprintf(output_file, "  %c %s", n == 0 ? ' ' : '|', bp->name);
  980.       if (bp->tag) {
  981.     /* If it may be a product or record, 
  982.            there is an abbreviation t__nn__ for it: */
  983.          if (strchr(bp->tag, '*') || strchr(bp->tag, '{')) {
  984.        fprintf(output_file, " of t__%d__", tyno);
  985.          tyno++; 
  986.          } else {
  987.        fprintf(output_file, " of %s", bp->tag); }
  988.       }
  989.       fprintf(output_file, "\n");
  990.       n++;
  991.     }
  992.   }
  993.   fprintf(output_file, "end;\n\n");
  994. }
  995.  
  996. initialize_grammar()
  997. {
  998.     nitems = 4;
  999.     maxitems = 300;
  1000.     pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  1001.     if (pitem == 0) no_space();
  1002.     pitem[0] = 0;
  1003.     pitem[1] = 0;
  1004.     pitem[2] = 0;
  1005.     pitem[3] = 0;
  1006.  
  1007.     nrules = 3;
  1008.     maxrules = 100;
  1009.     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  1010.     if (plhs == 0) no_space();
  1011.     plhs[0] = 0;
  1012.     plhs[1] = 0;
  1013.     plhs[2] = 0;
  1014.     rprec = (short *) MALLOC(maxrules*sizeof(short));
  1015.     if (rprec == 0) no_space();
  1016.     rprec[0] = 0;
  1017.     rprec[1] = 0;
  1018.     rprec[2] = 0;
  1019.     rassoc = (char *) MALLOC(maxrules*sizeof(char));
  1020.     if (rassoc == 0) no_space();
  1021.     rassoc[0] = TOKEN;
  1022.     rassoc[1] = TOKEN;
  1023.     rassoc[2] = TOKEN;
  1024. }
  1025.  
  1026.  
  1027. expand_items()
  1028. {
  1029.     maxitems += 300;
  1030.     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  1031.     if (pitem == 0) no_space();
  1032. }
  1033.  
  1034.  
  1035. expand_rules()
  1036. {
  1037.     maxrules += 100;
  1038.     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  1039.     if (plhs == 0) no_space();
  1040.     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  1041.     if (rprec == 0) no_space();
  1042.     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  1043.     if (rassoc == 0) no_space();
  1044. }
  1045.  
  1046.  
  1047. advance_to_start()
  1048. {
  1049.     register int c;
  1050.     register bucket *bp;
  1051.     char *s_cptr;
  1052.     int s_lineno;
  1053.  
  1054.     for (;;)
  1055.     {
  1056.     c = nextc();
  1057.     if (c != '%') break;
  1058.     s_cptr = cptr;
  1059.     switch (keyword())
  1060.     {
  1061.     case MARK:
  1062.         no_grammar();
  1063.  
  1064.     case TEXT:
  1065.         copy_text();
  1066.         break;
  1067.  
  1068.     case START:
  1069.         declare_start();
  1070.         break;
  1071.  
  1072.     default:
  1073.         syntax_error(lineno, line, s_cptr);
  1074.     }
  1075.     }
  1076.  
  1077.     c = nextc();
  1078.     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
  1079.     syntax_error(lineno, line, cptr);
  1080.     bp = get_name();
  1081.     if (goal == 0)
  1082.     {
  1083.     if (bp->class == TERM)
  1084.         terminal_start(bp->name);
  1085.     goal = bp;
  1086.     }
  1087.  
  1088.     s_lineno = lineno;
  1089.     c = nextc();
  1090.     if (c == EOF) unexpected_EOF();
  1091.     if (c != ':') syntax_error(lineno, line, cptr);
  1092.     start_rule(bp, s_lineno);
  1093.     ++cptr;
  1094. }
  1095.  
  1096.  
  1097. start_rule(bp, s_lineno)
  1098. register bucket *bp;
  1099. int s_lineno;
  1100. {
  1101.     if (bp->class == TERM)
  1102.     terminal_lhs(s_lineno);
  1103.     bp->class = NONTERM;
  1104.     if (nrules >= maxrules)
  1105.     expand_rules();
  1106.     plhs[nrules] = bp;
  1107.     rprec[nrules] = UNDEFINED;
  1108.     rassoc[nrules] = TOKEN;
  1109. }
  1110.  
  1111.  
  1112. end_rule()
  1113. {
  1114.     register int i;
  1115.  
  1116.     if (!last_was_action && plhs[nrules]->tag)
  1117.     {
  1118.     for (i = nitems - 1; pitem[i]; --i) continue;
  1119.     if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
  1120.         default_action_warning();
  1121.     }
  1122.  
  1123.     last_was_action = 0;
  1124.     if (nitems >= maxitems) expand_items();
  1125.     pitem[nitems] = 0;
  1126.     ++nitems;
  1127.     ++nrules;
  1128. }
  1129.  
  1130.  
  1131. insert_empty_rule()
  1132. {
  1133.     register bucket *bp, **bpp;
  1134.  
  1135.     assert(cache);
  1136.     sprintf(cache, "$$%d", ++gensym);
  1137.     bp = make_bucket(cache);
  1138.     last_symbol->next = bp;
  1139.     last_symbol = bp;
  1140.     bp->tag = plhs[nrules]->tag;
  1141.     bp->class = NONTERM;
  1142.  
  1143.     if ((nitems += 2) > maxitems)
  1144.     expand_items();
  1145.     bpp = pitem + nitems - 1;
  1146.     *bpp-- = bp;
  1147.     while (bpp[0] = bpp[-1]) --bpp;
  1148.  
  1149.     if (++nrules >= maxrules)
  1150.     expand_rules();
  1151.     plhs[nrules] = plhs[nrules-1];
  1152.     plhs[nrules-1] = bp;
  1153.     rprec[nrules] = rprec[nrules-1];
  1154.     rprec[nrules-1] = 0;
  1155.     rassoc[nrules] = rassoc[nrules-1];
  1156.     rassoc[nrules-1] = TOKEN;
  1157. }
  1158.  
  1159.  
  1160. add_symbol()
  1161. {
  1162.     register int c;
  1163.     register bucket *bp;
  1164.     int s_lineno = lineno;
  1165.  
  1166.     c = *cptr;
  1167.     if (c == '\'' || c == '"')
  1168.     bp = get_literal();
  1169.     else
  1170.     bp = get_name();
  1171.  
  1172.     c = nextc();
  1173.     if (c == ':')
  1174.     {
  1175.     end_rule();
  1176.     start_rule(bp, s_lineno);
  1177.     ++cptr;
  1178.     return;
  1179.     }
  1180.  
  1181.     if (last_was_action)
  1182.     insert_empty_rule();
  1183.     last_was_action = 0;
  1184.  
  1185.     if (++nitems > maxitems)
  1186.     expand_items();
  1187.     pitem[nitems-1] = bp;
  1188. }
  1189.  
  1190.  
  1191. copy_action()
  1192. {
  1193.     register int c;
  1194.     register int i, n;
  1195.     int depth;
  1196.     int quote;
  1197.     bucket *item;
  1198.     char *tagres;
  1199.     register FILE *f = action_file;
  1200.     int a_lineno = lineno;
  1201.     char *a_line = dup_line();
  1202.     char *a_cptr = a_line + (cptr - line);
  1203.  
  1204.     if (last_was_action)
  1205.     insert_empty_rule();
  1206.     last_was_action = 1;
  1207.  
  1208.     fprintf(f, "(* Rule %d, file %s, line %d *)\n",
  1209.             nrules-2, input_file_name, lineno);
  1210.  
  1211.     n = 0;
  1212.     for (i = nitems - 1; pitem[i]; --i) ++n;
  1213.  
  1214.     /* Let-bind all $'s early in the semantic action, outside any function 
  1215.        closure:
  1216.  
  1217.        let val d__1__ = peekVal (n-1)
  1218.            val d__2__ = peekVal (n-2)
  1219.        ...
  1220.            val d__n__ = peekVal 0
  1221.        in ... semantic action ... 
  1222.        end
  1223.     */
  1224.     fprintf(f, "val _ = update_ yyact %d\n(fn () => repr(let\n", nrules-2);
  1225.     for (i = 1; i <= n; i++)
  1226.        { item = pitem[nitems + i - n - 1];
  1227.          if (item->tag) 
  1228.             fprintf(f, "val d__%d__ = peekVal %d : %s\n", i, n - i, item->tag);
  1229.        }        
  1230.     fprintf(f, "in\n(");
  1231.  
  1232.     depth = 1;
  1233.     cptr++;
  1234.  
  1235. loop:
  1236.     c = *cptr;
  1237.     if (c == '$')
  1238.     {
  1239.     if (isdigit(cptr[1]))
  1240.     {
  1241.         ++cptr;
  1242.         i = get_number();
  1243.  
  1244.             if (i <= 0 || i > n)
  1245.               unknown_rhs(i);
  1246.             item = pitem[nitems + i - n - 1];
  1247.             if (item->tag) {
  1248.               fprintf(f, "(d__%d__)", i);
  1249.             } else {
  1250.               if (item->class == TERM)
  1251.                 { illegal_token_ref(i, item->name); }
  1252.           else
  1253.         { missing_type(item->name); }
  1254.             /* This trick, which works in Caml Light and Edinburgh ML,  
  1255.              * cannot be used in Standard ML to improve type security:
  1256.              * if (sflag)
  1257.              *    fprintf(f, "(peekVal %d)", n - i);
  1258.              * else
  1259.              *    fprintf(f, "(peekVal %d : '%s)", n - i, item->name); 
  1260.              */
  1261.             }
  1262.         goto loop;
  1263.     }
  1264.     }
  1265.     if (isalpha(c) || c == '_' || c == '$')
  1266.     {
  1267.     do
  1268.     {
  1269.         putc(c, f);
  1270.         c = *++cptr;
  1271.     } while (isalnum(c) || c == '_' || c == '$');
  1272.     goto loop;
  1273.     }
  1274.     if (c == '}' && depth == 1) {
  1275.       cptr++;
  1276.       tagres = plhs[nrules]->tag;
  1277.       if (tagres)
  1278.         { fprintf(f, ") end : %s))\n", tagres); }
  1279.       else         
  1280.     { missing_type(plhs[nrules]->name); }
  1281.       /* Same problem as above: don't insert type ascriptions:
  1282.        * if (sflag)
  1283.        *  fprintf(f, ")))\n");
  1284.        * else
  1285.        *  fprintf(f, ") : '%s))\n", plhs[nrules]->name);
  1286.        */
  1287.       /* if (sflag) */
  1288.         fprintf(f, ";\n");
  1289.       return;
  1290.     }
  1291.     putc(c, f);
  1292.     ++cptr;
  1293.     switch (c)
  1294.     {
  1295.     case '\n':
  1296.     next_line:
  1297.     get_line();
  1298.     if (line) goto loop;
  1299.     unterminated_action(a_lineno, a_line, a_cptr);
  1300.  
  1301.     case '{':
  1302.     ++depth;
  1303.     goto loop;
  1304.  
  1305.     case '}':
  1306.     --depth;
  1307.         goto loop;
  1308.  
  1309.     case '`':
  1310.     case '"':
  1311.     {
  1312.         int s_lineno = lineno;
  1313.         char *s_line = dup_line();
  1314.         char *s_cptr = s_line + (cptr - line - 1);
  1315.  
  1316.         quote = c;
  1317.         for (;;)
  1318.         {
  1319.         c = *cptr++;
  1320.         putc(c, f);
  1321.         if (c == quote)
  1322.         {
  1323.             FREE(s_line);
  1324.             goto loop;
  1325.         }
  1326.         if (c == '\n')
  1327.             unterminated_string(s_lineno, s_line, s_cptr);
  1328.         if (c == '\\')
  1329.         {
  1330.             c = *cptr++;
  1331.             putc(c, f);
  1332.             if (c == '\n')
  1333.             {
  1334.             get_line();
  1335.             if (line == 0)
  1336.                 unterminated_string(s_lineno, s_line, s_cptr);
  1337.             }
  1338.         }
  1339.         }
  1340.     }
  1341.  
  1342.     case '(':
  1343.     c = *cptr;
  1344.     if (c == '*')
  1345.     {
  1346.         int c_lineno = lineno;
  1347.         char *c_line = dup_line();
  1348.         char *c_cptr = c_line + (cptr - line - 1);
  1349.  
  1350.         putc('*', f);
  1351.         ++cptr;
  1352.         for (;;)
  1353.         {
  1354.         c = *cptr++;
  1355.         putc(c, f);
  1356.         if (c == '*' && *cptr == ')')
  1357.         {
  1358.             putc(')', f);
  1359.             ++cptr;
  1360.             FREE(c_line);
  1361.             goto loop;
  1362.         }
  1363.         if (c == '\n')
  1364.         {
  1365.             get_line();
  1366.             if (line == 0)
  1367.             unterminated_comment(c_lineno, c_line, c_cptr);
  1368.         }
  1369.         }
  1370.     }
  1371.     goto loop;
  1372.  
  1373.     default:
  1374.     goto loop;
  1375.     }
  1376. }
  1377.  
  1378.  
  1379. int
  1380. mark_symbol()
  1381. {
  1382.     register int c;
  1383.     register bucket *bp;
  1384.  
  1385.     c = cptr[1];
  1386.     if (c == '%' || c == '\\')
  1387.     {
  1388.     cptr += 2;
  1389.     return (1);
  1390.     }
  1391.  
  1392.     if (c == '=')
  1393.     cptr += 2;
  1394.     else if ((c == 'p' || c == 'P') &&
  1395.          ((c = cptr[2]) == 'r' || c == 'R') &&
  1396.          ((c = cptr[3]) == 'e' || c == 'E') &&
  1397.          ((c = cptr[4]) == 'c' || c == 'C') &&
  1398.          ((c = cptr[5], !IS_IDENT(c))))
  1399.     cptr += 5;
  1400.     else
  1401.     syntax_error(lineno, line, cptr);
  1402.  
  1403.     c = nextc();
  1404.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  1405.     bp = get_name();
  1406.     else if (c == '\'' || c == '"')
  1407.     bp = get_literal();
  1408.     else
  1409.     {
  1410.     syntax_error(lineno, line, cptr);
  1411.     /*NOTREACHED*/
  1412.     }
  1413.  
  1414.     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1415.     prec_redeclared();
  1416.  
  1417.     rprec[nrules] = bp->prec;
  1418.     rassoc[nrules] = bp->assoc;
  1419.     return (0);
  1420. }
  1421.  
  1422.  
  1423. read_grammar()
  1424. {
  1425.     register int c;
  1426.  
  1427.     initialize_grammar();
  1428.     advance_to_start();
  1429.  
  1430.     for (;;)
  1431.     {
  1432.     c = nextc();
  1433.     if (c == EOF) break;
  1434.     if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
  1435.         c == '"')
  1436.         add_symbol();
  1437.     else if (c == '{' || c == '=')
  1438.         copy_action();
  1439.     else if (c == '|')
  1440.     {
  1441.         end_rule();
  1442.         start_rule(plhs[nrules-1], 0);
  1443.         ++cptr;
  1444.     }
  1445.     else if (c == '%')
  1446.     {
  1447.         if (mark_symbol()) break;
  1448.     }
  1449.     else
  1450.         syntax_error(lineno, line, cptr);
  1451.     }
  1452.     end_rule();
  1453. }
  1454.  
  1455.  
  1456. free_tags()
  1457. {
  1458.     register int i;
  1459.  
  1460.     if (tag_table == 0) return;
  1461.  
  1462.     for (i = 0; i < ntags; ++i)
  1463.     {
  1464.     assert(tag_table[i]);
  1465.     FREE(tag_table[i]);
  1466.     }
  1467.     FREE(tag_table);
  1468. }
  1469.  
  1470.  
  1471. pack_names()
  1472. {
  1473.     register bucket *bp;
  1474.     register char *p, *s, *t;
  1475.  
  1476.     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
  1477.     for (bp = first_symbol; bp; bp = bp->next)
  1478.     name_pool_size += strlen(bp->name) + 1;
  1479.     name_pool = MALLOC(name_pool_size);
  1480.     if (name_pool == 0) no_space();
  1481.  
  1482.     strcpy(name_pool, "$accept");
  1483.     strcpy(name_pool+8, "$end");
  1484.     t = name_pool + 13;
  1485.     for (bp = first_symbol; bp; bp = bp->next)
  1486.     {
  1487.     p = t;
  1488.     s = bp->name;
  1489.     while (*t++ = *s++) continue;
  1490.     FREE(bp->name);
  1491.     bp->name = p;
  1492.     }
  1493. }
  1494.  
  1495.  
  1496. check_symbols()
  1497. {
  1498.     register bucket *bp;
  1499.  
  1500.     if (goal->class == UNKNOWN)
  1501.     undefined_goal(goal->name);
  1502.  
  1503.     for (bp = first_symbol; bp; bp = bp->next)
  1504.     {
  1505.     if (bp->class == UNKNOWN)
  1506.     {
  1507.         undefined_symbol_warning(bp->name);
  1508.         bp->class = TERM;
  1509.     }
  1510.     }
  1511. }
  1512.  
  1513.  
  1514. pack_symbols()
  1515. {
  1516.     register bucket *bp;
  1517.     register bucket **v;
  1518.     register int i, j, k, n;
  1519.  
  1520.     nsyms = 2;
  1521.     ntokens = 1;
  1522.     for (bp = first_symbol; bp; bp = bp->next)
  1523.     {
  1524.     ++nsyms;
  1525.     if (bp->class == TERM) ++ntokens;
  1526.     }
  1527.     start_symbol = ntokens;
  1528.     nvars = nsyms - ntokens;
  1529.  
  1530.     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1531.     if (symbol_name == 0) no_space();
  1532.     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1533.     if (symbol_value == 0) no_space();
  1534.     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1535.     if (symbol_prec == 0) no_space();
  1536.     symbol_assoc = MALLOC(nsyms);
  1537.     if (symbol_assoc == 0) no_space();
  1538.     symbol_tag = (char **) MALLOC(nsyms*sizeof(char *));
  1539.     if (symbol_tag == 0) no_space();
  1540.     symbol_true_token = (char *) MALLOC(nsyms*sizeof(char));
  1541.     if (symbol_true_token == 0) no_space();
  1542.  
  1543.     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1544.     if (v == 0) no_space();
  1545.  
  1546.     v[0] = 0;
  1547.     v[start_symbol] = 0;
  1548.  
  1549.     i = 1;
  1550.     j = start_symbol + 1;
  1551.     for (bp = first_symbol; bp; bp = bp->next)
  1552.     {
  1553.     if (bp->class == TERM)
  1554.         v[i++] = bp;
  1555.     else
  1556.         v[j++] = bp;
  1557.     }
  1558.     assert(i == ntokens && j == nsyms);
  1559.  
  1560.     for (i = 1; i < ntokens; ++i)
  1561.     v[i]->index = i;
  1562.  
  1563.     goal->index = start_symbol + 1;
  1564.     k = start_symbol + 2;
  1565.     while (++i < nsyms)
  1566.     if (v[i] != goal)
  1567.     {
  1568.         v[i]->index = k;
  1569.         ++k;
  1570.     }
  1571.  
  1572.     goal->value = 0;
  1573.     k = 1;
  1574.     for (i = start_symbol + 1; i < nsyms; ++i)
  1575.     {
  1576.     if (v[i] != goal)
  1577.     {
  1578.         v[i]->value = k;
  1579.         ++k;
  1580.     }
  1581.     }
  1582.  
  1583.     k = 0;
  1584.     for (i = 1; i < ntokens; ++i)
  1585.     {
  1586.     n = v[i]->value;
  1587.     if (n > 256)
  1588.     {
  1589.         for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1590.         symbol_value[j] = symbol_value[j-1];
  1591.         symbol_value[j] = n;
  1592.     }
  1593.     }
  1594.  
  1595.     if (v[1]->value == UNDEFINED)
  1596.     v[1]->value = 256;
  1597.  
  1598.     j = 0;
  1599.     n = 257;
  1600.     for (i = 2; i < ntokens; ++i)
  1601.     {
  1602.     if (v[i]->value == UNDEFINED)
  1603.     {
  1604.         while (j < k && n == symbol_value[j])
  1605.         {
  1606.         while (++j < k && n == symbol_value[j]) continue;
  1607.         ++n;
  1608.         }
  1609.         v[i]->value = n;
  1610.         ++n;
  1611.     }
  1612.     }
  1613.  
  1614.     symbol_name[0] = name_pool + 8;
  1615.     symbol_value[0] = 0;
  1616.     symbol_prec[0] = 0;
  1617.     symbol_assoc[0] = TOKEN;
  1618.     symbol_tag[0] = "";
  1619.     symbol_true_token[0] = 0;
  1620.     for (i = 1; i < ntokens; ++i)
  1621.     {
  1622.     symbol_name[i] = v[i]->name;
  1623.     symbol_value[i] = v[i]->value;
  1624.     symbol_prec[i] = v[i]->prec;
  1625.     symbol_assoc[i] = v[i]->assoc;
  1626.     symbol_tag[i] = v[i]->tag;
  1627.     symbol_true_token[i] = v[i]->true_token;
  1628.     }
  1629.     symbol_name[start_symbol] = name_pool;
  1630.     symbol_value[start_symbol] = -1;
  1631.     symbol_prec[start_symbol] = 0;
  1632.     symbol_assoc[start_symbol] = TOKEN;
  1633.     symbol_tag[start_symbol] = "";
  1634.     symbol_true_token[start_symbol] = 0;
  1635.     for (++i; i < nsyms; ++i)
  1636.     {
  1637.     k = v[i]->index;
  1638.     symbol_name[k] = v[i]->name;
  1639.     symbol_value[k] = v[i]->value;
  1640.     symbol_prec[k] = v[i]->prec;
  1641.     symbol_assoc[k] = v[i]->assoc;
  1642.     symbol_tag[i] = v[i]->tag;
  1643.     symbol_true_token[i] = v[i]->true_token;
  1644.     }
  1645.  
  1646.     FREE(v);
  1647. }
  1648.  
  1649.  
  1650. make_goal()
  1651. {
  1652.   static char name[7] = "'\\xxx'";
  1653.   bucket * bp;
  1654.   bucket * bc;
  1655.  
  1656.   goal = lookup("%entry%");
  1657.   ntotalrules = nrules - 2;
  1658.   for(bp = first_symbol; bp != 0; bp = bp->next) {
  1659.     if (bp->entry) {
  1660.       start_rule(goal, 0);
  1661.       if (nitems + 2> maxitems)
  1662.     expand_items();
  1663.       name[2] = '0' + ((bp->entry >> 6) & 7);
  1664.       name[3] = '0' + ((bp->entry >> 3) & 7);
  1665.       name[4] = '0' + (bp->entry & 7);
  1666.       bc = lookup(name);
  1667.       bc->class = TERM;
  1668.       bc->value = (unsigned char) bp->entry;
  1669.       pitem[nitems++] = bc;
  1670.       pitem[nitems++] = bp;
  1671.       fprintf(entry_file,
  1672.               "fun %s lexer lexbuf = yyparse yytables %d lexer lexbuf;\n",
  1673.               bp->name, bp->entry);
  1674.       fprintf(interface_file,
  1675.               "val %s :\n  (Lexing.lexbuf -> token) -> Lexing.lexbuf -> %s;\n",
  1676.               bp->name,
  1677.               bp->tag);
  1678.       fprintf(action_file,
  1679.               "(* Entry %s *)\n", bp->name);
  1680.       fprintf(action_file,
  1681.        "val _ = update_ yyact %d (fn () => raise yyexit (peekVal 0));\n",
  1682.        ntotalrules);
  1683.       ntotalrules++;
  1684.       last_was_action = 1;
  1685.       end_rule();
  1686.     }
  1687.   }
  1688. }
  1689.  
  1690. pack_grammar()
  1691. {
  1692.     register int i, j;
  1693.     int assoc, prec;
  1694.  
  1695.     ritem = (short *) MALLOC(nitems*sizeof(short));
  1696.     if (ritem == 0) no_space();
  1697.     rlhs = (short *) MALLOC(nrules*sizeof(short));
  1698.     if (rlhs == 0) no_space();
  1699.     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1700.     if (rrhs == 0) no_space();
  1701.     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1702.     if (rprec == 0) no_space();
  1703.     rassoc = REALLOC(rassoc, nrules);
  1704.     if (rassoc == 0) no_space();
  1705.  
  1706.     ritem[0] = -1;
  1707.     ritem[1] = goal->index;
  1708.     ritem[2] = 0;
  1709.     ritem[3] = -2;
  1710.     rlhs[0] = 0;
  1711.     rlhs[1] = 0;
  1712.     rlhs[2] = start_symbol;
  1713.     rrhs[0] = 0;
  1714.     rrhs[1] = 0;
  1715.     rrhs[2] = 1;
  1716.  
  1717.     j = 4;
  1718.     for (i = 3; i < nrules; ++i)
  1719.     {
  1720.     rlhs[i] = plhs[i]->index;
  1721.     rrhs[i] = j;
  1722.     assoc = TOKEN;
  1723.     prec = 0;
  1724.     while (pitem[j])
  1725.     {
  1726.         ritem[j] = pitem[j]->index;
  1727.         if (pitem[j]->class == TERM)
  1728.         {
  1729.         prec = pitem[j]->prec;
  1730.         assoc = pitem[j]->assoc;
  1731.         }
  1732.         ++j;
  1733.     }
  1734.     ritem[j] = -i;
  1735.     ++j;
  1736.     if (rprec[i] == UNDEFINED)
  1737.     {
  1738.         rprec[i] = prec;
  1739.         rassoc[i] = assoc;
  1740.     }
  1741.     }
  1742.     rrhs[i] = j;
  1743.  
  1744.     FREE(plhs);
  1745.     FREE(pitem);
  1746. }
  1747.  
  1748.  
  1749. print_grammar()
  1750. {
  1751.     register int i, j, k;
  1752.     int spacing;
  1753.     register FILE *f = verbose_file;
  1754.  
  1755.     if (!vflag) return;
  1756.  
  1757.     k = 1;
  1758.     for (i = 2; i < nrules; ++i)
  1759.     {
  1760.     if (rlhs[i] != rlhs[i-1])
  1761.     {
  1762.         if (i != 2) fprintf(f, "\n");
  1763.         fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
  1764.         spacing = strlen(symbol_name[rlhs[i]]) + 1;
  1765.     }
  1766.     else
  1767.     {
  1768.         fprintf(f, "%4d  ", i - 2);
  1769.         j = spacing;
  1770.         while (--j >= 0) putc(' ', f);
  1771.         putc('|', f);
  1772.     }
  1773.  
  1774.     while (ritem[k] >= 0)
  1775.     {
  1776.         fprintf(f, " %s", symbol_name[ritem[k]]);
  1777.         ++k;
  1778.     }
  1779.     ++k;
  1780.     putc('\n', f);
  1781.     }
  1782. }
  1783.  
  1784.  
  1785. reader()
  1786. {
  1787.     create_symbol_table();
  1788.     read_declarations();
  1789.     output_token_type(interface_file);
  1790.     output_token_type(code_file);
  1791.     read_grammar();
  1792.     make_goal();
  1793.     free_symbol_table();
  1794.     free_tags();
  1795.     pack_names();
  1796.     check_symbols();
  1797.     pack_symbols();
  1798.     pack_grammar();
  1799.     free_symbols();
  1800.     print_grammar();
  1801. }
  1802.